import { createRef, forwardRef, useImperativeHandle, useRef, useState } from 'react';

import { Modal, ModalProps } from 'antd';

import { ElementsHolder, ElementsHolderRef } from '../elementsHolder';

export type HookModalProps = {
  afterClose: () => void;
  config: ModalProps;
};
export type HookModalRef = {
  destroy: () => void;
  update: (config: ModalProps) => void;
};

const HookModal = forwardRef<HookModalRef, HookModalProps>(
  ({ afterClose: hookAfterClose, config }, ref) => {
    const [open, setOpen] = useState(true);
    const [innerConfig, setInnerConfig] = useState(config);

    const afterClose = () => {
      hookAfterClose();
      innerConfig.afterClose?.();
    };

    const close = () => {
      setOpen(false);
    };

    useImperativeHandle(ref, () => {
      return {
        destroy: close,
        update: (newConfig) => {
          setInnerConfig((prev) => ({
            ...prev,
            ...newConfig
          }));
        }
      };
    });

    return (
      <Modal footer={null} {...innerConfig} open={open} onCancel={close} afterClose={afterClose} />
    );
  }
);

// ===========================

export type ModalHookAPI = {
  open: (config?: ModalProps) => {
    destroy: () => void;
    update: (config: ModalProps) => void;
  };
};

let uuid = 0;

export const useModal = () => {
  const holderRef = useRef<ElementsHolderRef>(null);

  const fns: ModalHookAPI = {
    open: (config) => {
      uuid += 1;
      const modalRef = createRef<HookModalRef>();

      // eslint-disable-next-line prefer-const
      let closeFunc: (() => void) | undefined;

      const modal = (
        <HookModal
          key={`modal-${uuid}`}
          config={config || {}}
          ref={modalRef}
          afterClose={() => {
            closeFunc?.();
          }}
        />
      );

      closeFunc = holderRef.current?.patchElement(modal);

      return {
        destroy: () => {
          modalRef.current?.destroy();
        },
        update: (newConfig: ModalProps) => {
          modalRef.current?.update(newConfig);
        }
      };
    }
  };

  return [fns, <ElementsHolder key="modal-holder" ref={holderRef} />] as readonly [
    instance: ModalHookAPI,
    contextHolder: React.ReactElement
  ];
};
